﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model;
using l1cs.server.model.Instance;
using l1cs.server.templates;
using l1cs.server.model.skill;

namespace l1cs.server.serverpackets
{
    public class AtomicInteger
    {
        private static int _i;

        public AtomicInteger( int i )
        {
            _i = i;
        }

        public int incrementAndGet()
        {
            lock ( this )
            {
                return _i++;
            }
        }
    }

    public class S_UseAttackSkill : ServerBasePacket
    {
        private static Logger _log = Logger.getLogger( typeof( S_UseAttackSkill ).FullName );

        private static AtomicInteger _sequentialNumber = new AtomicInteger( 0 );

        private byte[] _byte = null;

        public S_UseAttackSkill( L1Character cha, int targetobj, int spellgfx, int x, int y, int actionId )
        {
            buildPacket( cha, targetobj, spellgfx, x, y, actionId, 6, true );
        }

        public S_UseAttackSkill( L1Character cha, int targetobj, int spellgfx, int x, int y, int actionId, bool motion )
        {
            buildPacket( cha, targetobj, spellgfx, x, y, actionId, 0, motion );
        }

        public S_UseAttackSkill( L1Character cha, int targetobj, int spellgfx, int x, int y, int actionId, int isHit )
        {
            buildPacket( cha, targetobj, spellgfx, x, y, actionId, isHit, true );
        }

        private void buildPacket( L1Character cha, int targetobj, int spellgfx, int x, int y, int actionId, int isHit, bool withCastMotion )
        {
            if ( cha is L1PcInstance )
            {
                // シャドウ系変身中に攻撃魔法を使用するとクライアントが落ちるため暫定対応
                if ( cha.hasSkillEffect( L1SkillId.SHAPE_CHANGE )
                        && actionId == ActionCodes.ACTION_SkillAttack )
                {
                    int tempchargfx = cha.getTempCharGfx();
                    if ( tempchargfx == 5727 || tempchargfx == 5730 )
                    {
                        actionId = ActionCodes.ACTION_SkillBuff;
                    }
                    else if ( tempchargfx == 5733 || tempchargfx == 5736 )
                    {
                        // 補助魔法モーションにすると攻撃魔法のグラフィックと
                        // 対象へのダメージモーションが発生しなくなるため
                        // 攻撃モーションで代用
                        actionId = ActionCodes.ACTION_Attack;
                    }
                }
            }
            // 火の精の主がデフォルトだと攻撃魔法のグラフィックが発生しないので強制置き換え
            // どこか別で管理した方が良い？
            if ( cha.getTempCharGfx() == 4013 )
            {
                actionId = ActionCodes.ACTION_Attack;
            }

            int newheading = calcheading( cha.getX(), cha.getY(), x, y );
            cha.setHeading( newheading );
            writeC( Opcodes.S_OPCODE_ATTACKPACKET );
            writeC( actionId );
            writeD( withCastMotion ? cha.getId() : 0 );
            writeD( targetobj );
            writeC( isHit );
            writeC( newheading );
            writeD( _sequentialNumber.incrementAndGet() ); // 番号がダブらないように送る。
            writeH( spellgfx );
            writeC( 6 ); // タケッジゾング:6,範囲&タケッジゾング:8,範囲:0
            writeH( cha.getX() );
            writeH( cha.getY() );
            writeH( x );
            writeH( y );
            writeC( 0 );
            writeC( 0 );
            writeC( 0 );
            writeC( 0 );
            writeC( 0 );
        }

        override
        public byte[] getContent()
        {
            if ( _byte == null )
            {
                _byte = _bao.ToArray();
            }
            else
            {
                int seq = _sequentialNumber.incrementAndGet();
                _byte[12] = (byte)( seq & 0xff );
                _byte[13] = (byte)( seq >> 8 & 0xff );
                _byte[14] = (byte)( seq >> 16 & 0xff );
                _byte[15] = (byte)( seq >> 24 & 0xff );
            }

            return _byte;
        }

        private static int calcheading( int myx, int myy, int tx, int ty )
        {
            int newheading = 0;
            if ( tx > myx && ty > myy )
            {
                newheading = 3;
            }
            if ( tx < myx && ty < myy )
            {
                newheading = 7;
            }
            if ( tx > myx && ty == myy )
            {
                newheading = 2;
            }
            if ( tx < myx && ty == myy )
            {
                newheading = 6;
            }
            if ( tx == myx && ty < myy )
            {
                newheading = 0;
            }
            if ( tx == myx && ty > myy )
            {
                newheading = 4;
            }
            if ( tx < myx && ty > myy )
            {
                newheading = 5;
            }
            if ( tx > myx && ty < myy )
            {
                newheading = 1;
            }
            return newheading;
        }

        override
        public String getType()
        {
            return "[S] S_UseAttackSkill";
        }

    }
}
